package org.lc.service.system.service.impl;

import com.baomidou.mybatisplus.extension.toolkit.Db;
import org.lc.platform.base.annotation.auth.CurrentUser;
import org.lc.platform.base.vo.TreeListVo;
import org.lc.platform.boot.util.LcAuthUtils;
import org.lc.platform.mybatis.crud.service.impl.CrudBaseServiceImpl;
import org.lc.platform.mybatis.manager.query.QueryBuilder;
import org.lc.service.system.dto.SysMenuDto;
import org.lc.service.system.entity.SysMenu;
import org.lc.service.system.entity.SysPermission;
import org.lc.service.system.entity.SysRoleAclApi;
import org.lc.service.system.entity.SysRolePermission;
import org.lc.service.system.mapper.SysMenuMapper;
import org.lc.service.system.service.SysMenuService;
import org.lc.service.system.service.SysUserService;
import org.lc.service.system.util.ConstantUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;


@Service
public class SysMenuServiceImpl extends CrudBaseServiceImpl<SysMenuDto, SysMenu, SysMenuMapper, SysMenu> implements SysMenuService {

    @Autowired
    SysUserService user;

    @Override
    public SysMenu Convertor(SysMenu data) {
        return data;
    }

    @Override
    public QueryBuilder<SysMenu> getQueryBuilder(SysMenuDto query, QueryBuilder<SysMenu> queryBuilder) {
        if ("noParent".equals(query.getParentId())) {
            queryBuilder.isNull("parent_id");
        } else {
            queryBuilder.eq(query.getParentId() != null, "parent_id", query.getParentId());
            queryBuilder.relation(SysMenu.class);
        }
        queryBuilder.like(query.getText() != null, "text", query.getText());
        return queryBuilder;
    }

    @Override
    public List<SysMenu> getMenuTreeList() {
        return this.manager.createQueryBuilder().isNull("parent_id").selectTreeLevel();
    }

    @Override
    public Map<String, Object> getMenuTreeAcl(String role) {
        var query = Db.lambdaQuery(SysRolePermission.class).eq(SysRolePermission::getSysRoleId, role);
        var rp = Db.list(query.getWrapper());
        Map<String, Object> maps = new HashMap<>();
        if (rp != null) {
            maps.put("keys", rp.stream().map(SysRolePermission::getSysPermissionId).toList());
        }
        var userInfo = LcAuthUtils.getCurrentUser();
        List<String> keys = new ArrayList<>();
        if (!userInfo.isSuperAdmin()) {
            keys = user.getSysRoleAclApi(userInfo.getUserId()).stream().map(SysRoleAclApi::getPermission).toList();
        }
        var data = this.manager.createQueryBuilder().relation(SysPermission.class).isNull("parent_id").selectTreeLevel();
        maps.put("data", deepMapMenu(data, keys, userInfo.isSuperAdmin()));
        return maps;
    }


    private List<TreeListVo> deepMapMenu(List<SysMenu> menus, List<String> keys, Boolean isAdmin) {
        if (menus == null) {
            return null;
        }
        return menus.stream().map(r -> {
            TreeListVo tree = new TreeListVo();
            tree.setId(r.getId());
            tree.setDisabled(r.getForbidden());
            tree.setLabel(r.getText());
            if (r.getIsLeaf() && r.getPermissions() != null) {
                var res = r.getPermissions().stream();
                if (!isAdmin && keys != null) {
                    res = res.filter(fs -> keys.contains(fs.getId()));
                }
                tree.setChildren(
                        res.map(p -> {
                            TreeListVo childTree = new TreeListVo();
                            childTree.setId(p.getId());

                            childTree.setLeaf(true);
                            childTree.setLabel(p.getName());
                            return childTree;
                        }).toList());
            }
            if (!r.getIsLeaf()) {
                tree.setLeaf(false);
                tree.setChildren(deepMapMenu(r.getChildren(), keys, isAdmin));
            }
            return tree;
        }).filter(f -> f.isLeaf() || !f.getChildren().isEmpty()).toList();
    }

    @Override
    @Transactional
    public Boolean createBaseOne(SysMenu body) {
        super.createBaseOne(body);
        if (body.getIsLeaf()) {
            Db.saveBatch(ConstantUtil.getCrudPermission(body.getId(),body.getModa()));
        }
        return true;
    }
}